﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using WinForm=System.Windows.Forms;
using System.Drawing.Design;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using Arthasliu.Uti;

namespace Arthasliu.Controls
{
    public partial class IntelligentSuggestion : Component
    {
        public IntelligentSuggestion()
        {
            InitializeComponent();


            RootContainer = null;
            ReInitial = true;
            DisplayedColumns = new List<string>();
            ColumnAlias = new Dictionary<string, string>();
            Subscribed = false;
        }

        public IntelligentSuggestion(IContainer container):this()
        {
            container.Add(this);

            //InitializeComponent();

        }

        /// <summary>
        /// margin
        /// </summary>
        public Padding Margin
        {
            get
            {
                return autoDataGridView.Margin;
            }
            set
            {
                autoDataGridView.Margin = value;
            }
        }

        [DefaultValue("")]
        public object DataSource
        {
            get;
            set;
        }


        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Editor("System.Windows.Forms.Design.DataGridViewColumnCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
        [MergableProperty(false)]
        public WinForm.DataGridViewColumnCollection Columns
        {
            get
            {
                return autoDataGridView.Columns;
            }
        }

        public WinForm.Control RootContainer
        {
            get;
            private set;
        }

        public bool ReInitial
        {
            get;
            private set;
        }

        /// <summary>
        /// column's name need to be hidden
        /// </summary>
        public List<string> DisplayedColumns
        {
            get;
            private set;
        }

        private bool isInDisplayedColumns(string columnName)
        {
            foreach (var myCol in DisplayedColumns)
            {
                if (myCol.ToLower()==columnName.ToLower())
                {
                    return true;
                }
            }
            return false;
        }

        //alias of columns
        public Dictionary<string, string> ColumnAlias
        {
            get;
            private set;
        }

        [DefaultValue("")]
        public string FilterColumn
        {
            get;
            set;
        }

        /// <summary>
        ///whether this control has subscribed other control
        /// </summary>
        public bool Subscribed
        {
            get;
            private set;
        }

        /// <summary>
        /// handle event when suggestion has been accepted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void SuggestionAcceptedEventHandler(object sender, TemplatedEventArgs<DataGridViewSelectedRowCollection> e);

        /// <summary>
        /// raise when suggestion is been accepted
        /// </summary>
        public event SuggestionAcceptedEventHandler SuggestionAcceptedEvent;


        public void Subscribe(WinForm.Control publisher)
        {
            //get container once
            if (RootContainer==null)
            {
                RootContainer = publisher;

                while (true)
                {
                    if (RootContainer.Parent==null)
                    {
                        break;
                    }
                    RootContainer = RootContainer.Parent;
                }
            }

            publisher.KeyUp += new KeyEventHandler(publisher_KeyUp);
            publisher.KeyPress += new KeyPressEventHandler(publisher_KeyPress);

            Subscribed = true;
        }


        void publisher_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar==(char)Keys.Enter||e.KeyChar==(char)Keys.Escape)
            {
                e.Handled = true;      
            }
        }

        /// <summary>
        /// force hide this control
        /// </summary>
        [DefaultValue(false)]
        public bool ForceHide
        {
            get
            {
                return forceHide;
            }
            set
            {
                forceHide = value;

                if (value==true)
                {
                    autoDataGridView.Visible = false;
                }
            }
        }

        private bool forceHide;

        public void Show()
        {
            if (forceHide==true)
            {
                return;
            }
            autoDataGridView.Visible = true;
        }

        void publisher_KeyUp(object sender, KeyEventArgs e)
        {
            //force hide not response
            if (forceHide==true)
            {
                return;
            }


            //when esc hide
            if (e.KeyCode==Keys.Escape)
            {
                autoDataGridView.Visible = false;
                return;
            }

            Control myCtrl = sender as Control;

            if (myCtrl == null)
            {
                return;
            }

            //accept suggestion
            if (e.KeyCode == Keys.Enter)
            {
                autoDataGridView.Visible = false;

                var myRow = autoDataGridView.SelectedRows;

                if (myRow==null||myRow.Count==0)
                {
                    return;
                }

                //raise accept event
                if (SuggestionAcceptedEvent != null)
                {
                    SuggestionAcceptedEvent(this, new TemplatedEventArgs<DataGridViewSelectedRowCollection>(myRow));
                }

                return;
            }

            if (e.KeyCode == Keys.Up)
            {
                Setp2NextRow(-1, myCtrl);
                return;
            }

            if (e.KeyCode == Keys.Down)
            {
                Setp2NextRow(1, myCtrl);
                return;
            }

            //other common key
            var myControl = sender as WinForm.Control;

            //need reinitialize
            if (ReInitial == true)
            {
                RootContainer.Controls.Add(autoDataGridView);

                ReInitial = false;
            }

            //relocate position
            autoDataGridView.Location = RootContainer.PointToClient(myControl.Parent.PointToScreen(new Point { X = myControl.Left, Y = myControl.Top + myControl.Height + Margin.Top }));
            autoDataGridView.BringToFront();
                

            var myOriDv = autoDataGridView.DataSource as DataView;

            //initialize data source once
            if (myOriDv==null||myOriDv.Count==0)
            {
                var myTable = DataSource as DataTable;
                myOriDv = new DataView(myTable);

                autoDataGridView.DataSource = myOriDv;
            }

            var myFilter = myControl.Text;

            myOriDv.RowFilter = string.IsNullOrEmpty(myFilter) == true ? string.Empty : string.Format("{0} like '%{1}%'", FilterColumn, myControl.Text);

            //reinitial columns
            for (int i = 0; i < autoDataGridView.Columns.Count;i++ )
            {
                try
                {
                    var myCol = autoDataGridView.Columns[i];

                    if (isInDisplayedColumns(myCol.Name) == true)
                    {
                        myCol.Visible = true;
                    }
                    else
                    {
                        myCol.Visible = false;
                    }
                }
                catch (NullReferenceException)
                {
                	
                }
            }


            //rename columns
            foreach (var myAlia in ColumnAlias)
            {
                try
                {
                    Columns[myAlia.Key].HeaderText = myAlia.Value;
                }
                catch (NullReferenceException)
                {

                }
            }

            Show();
        }


        private void Setp2NextRow(int step, WinForm.Control sender)
        {

            var myCount = autoDataGridView.Rows.Count;

            //avoid head out of range
            step = step % myCount;

            //avoid tail out of range
            int myIndex = (autoDataGridView.SelectedRows[0].Index + myCount + step) % myCount;

            autoDataGridView.Rows[myIndex].Selected = true;

            autoDataGridView.FirstDisplayedScrollingRowIndex = myIndex;

            TextBoxBase myTextBox = sender as TextBoxBase;

            if (myTextBox==null)
            {
                return;
            }

            myTextBox.SelectionStart = myTextBox.Text.Length;
        }

        private void autoDataGridView_DoubleClick(object sender, EventArgs e)
        {
            var mySelected = autoDataGridView.SelectedRows;

            if (mySelected==null||mySelected.Count==0)
            {
                return;
            }

            if (SuggestionAcceptedEvent!=null)
            {
                SuggestionAcceptedEvent(sender, new TemplatedEventArgs<DataGridViewSelectedRowCollection>(mySelected));
            }

            autoDataGridView.Visible = false;
        }


    }

}
